<?php

namespace addons\xiluedu\controller;

use app\common\model\Readorder;
use app\common\model\xiluedu\CourseOrder;
use app\common\model\xiluedu\OfflineOrder;
use app\common\model\xiluedu\VipOrder;
use EasyWeChat\Factory;
use fast\Random;
use think\Cache;
use think\Cookie;
use think\Db;
use think\Exception;
use think\Log;


/**
 * 微信接口
 */
class WeixinPublic extends \think\Controller
{

    public $app = null;
    public $payment = null;

    public function _initialize()
    {
        parent::_initialize();
        $wxpublic_config = \app\common\model\xiluedu\Config::getMyConfig('wxpublic');
        $pay_config = \app\common\model\xiluedu\Config::getMyConfig('wxpayment');
        $config = [
            /**
             * 账号基本信息，请从小程序获取
             */
            'app_id'        => $wxpublic_config['wxpublic_appid'], // AppID
            'secret'        => $wxpublic_config['wxpublic_secret'], // AppSecret

            'response_type' => 'array',
            /**
             * 日志配置
             * level: 日志级别, 可选为：debug/info/notice/warning/error/critical/alert/emergency
             * path：日志文件位置(绝对路径!!!)，要求可写权限
             */
            'log'           => [
                'default'  => 'dev', // 默认使用的 channel，生产环境可以改为下面的 prod
                'channels' => [
                    // 测试环境
                    'dev'  => [
                        'driver' => 'single',
                        'path'   => ROOT_PATH . '/runtime/log/easywechat.log',
                        'level'  => 'debug',
                    ],
                    // 生产环境
                    'prod' => [
                        'driver' => 'daily',
                        'path'   => ROOT_PATH . '/runtime/log/easywechat.log',
                        'level'  => 'debug',
                    ],
                ],
            ],

            /**
             * OAuth 配置
             *
             * scopes：公众平台（snsapi_userinfo / snsapi_base），开放平台：snsapi_login
             * callback：OAuth授权完成后的回调页地址
             */
            'oauth' => [
                'scopes'   => ['snsapi_userinfo'],
                'callback' => $wxpublic_config['wxpublic_site'],
            ],
        ];
        $this->app = Factory::officialAccount($config);
        $payment_config = [
            // 必要配置
            'app_id'             => $wxpublic_config['wxpublic_appid'] ?? '',
            'mch_id'             => $pay_config['mch_id'] ?? '',
            'key'                => $pay_config['mch_key'] ?? '',   // API 密钥
            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            //'cert_path'          => $pay_config['apiclient_cert'] ?? '', // XXX: 绝对路径！！！！
            'cert_path'          => ROOT_PATH.'/public/cert/apiclient_cert.pem', // XXX: 绝对路径！！！！
            //'key_path'           => $pay_config['apiclient_key'] ?? '',      // XXX: 绝对路径！！！！
            'key_path'           => ROOT_PATH.'public/cert/apiclient_key.pem',      // XXX: 绝对路径！！！！
            'notify_url'         => '',     // 你也可以在下单时单独设置来想覆盖它
        ];
        $this->payment = Factory::payment($payment_config);
    }

    /**
     *
     */
    public function index()
    {
        $this->error("当前插件暂无前台页面");
    }

    /**
     * 微信API对接接口
     */
    public function api()
    {
        $this->app->server->setMessageHandler(function ($message) {


            $this->openid = $message->FromUserName;
            $to_openid = $message->ToUserName;
            $event = $message->Event;
            $eventkey = $message->EventKey ? $message->EventKey : $message->Event;


            switch ($message->MsgType) {
                case 'event': //事件消息
                    switch (strtolower($event)) {
                        case 'subscribe'://添加关注

                            //点击关注生成二维码和水印
                            if (!empty($message->EventKey) && false === stripos($message->EventKey, 'last_trade_no_')) {
                                $num = trim($message->EventKey, 'qrscene_');
                                $this->after_scan($num, $this->openid);
                            }


                            return "欢迎关注";
                            break;
                        case 'unsubscribe'://取消关注
                            return '';
                        case 'location'://获取地理位置
                            return '';
                        case 'view': //跳转链接,eventkey为链接
                            return '';
                        case 'scan':
                            $num = $message->EventKey;
                            return $this->after_scan($num, $this->openid);
                            break;
                        default:
                            break;
                    }
                    break;
                case 'text': //文字消息
                case 'image': //图片消息
                case 'voice': //语音消息
                case 'video': //视频消息
                case 'location': //坐标消息
                case 'link': //链接消息
                default: //其它消息

                    return '';

            }
            return ""; //SUCCESS
        });
        $response = $this->app->server->serve();
        // 将响应输出
        $response->send();
    }

    //生成二维码
    public function qrcode1($code = null, $expire = 0)
    {
        $app = $this->app;
        $qrcode = $app->qrcode;
        try {
            if ($expire) {
                $result = $qrcode->temporary($code, $expire);
                $ticket = $result->ticket; // 或者 $result['ticket']
                $expireSeconds = $result->expire_seconds; // 有效秒数
                $url = $result->url; // 二维码图片解析后的地址，开发者可根据该地址自行生成需要的二维码图片
            } else {
                //创建永久二维码
                $result = $qrcode->forever($code); // 或者 $qrcode->forever("foo");
                $ticket = $result->ticket; // 或者 $result['ticket']
            }
            $url = $qrcode->url($ticket);
            return [
                'status' => 1,
                'info' => '生成成功',
                'data' => ['ticket' => $ticket, 'url' => $url],
            ];
        } catch (\Exception $e) {
            //pubu("生成{$code}, 有效期为{$expire}秒的二维码失败");
            return ['status' => 0, 'info' => $e->getMessage()];
        }
    }


    //生成jsapi 配置
    public function jsapi($APIs, $url = '')
    {
//        if(get_platform()!='weixin'){
//            return [];
//        }
        $js = $this->app->jssdk;

        if ($url) {
            $js->setUrl($url);
        }
        return $js->buildConfig($APIs, $debug = false, $beta = false, $json = true);
    }

    //授权登录
    public function auth()
    {
        try {
            $response = $this->app->oauth->redirect();
            $response->send();
        } catch (\Exception $e) {
            dump("授权失败." . $e->getMessage());
        }
    }

    // 授权登录后的回调页面
    public function auth_back()
    {
        $code = $this->request->param('code');
        if (empty($code)) {
            $this->error('code 参数缺少');
        }
        $oauth = $this->app->oauth;
        // 获取 OAuth 授权结果用户信息
        $authUser = $oauth->user()->toArray();
        $wechat_userinfo = $authUser['original'];


//        $third_model = new Third();
//        $third = $third_model->where('openid',$wechat_userinfo['openid'])->where('platform','wxpublic')->find();
//        $param = [
//            'platform'  =>  'wxpublic',
//            'openid'    =>  $wechat_userinfo['openid'],
//            'openname'  =>  $wechat_userinfo['nickname'],
//            'avatar'    =>  $wechat_userinfo['headimgurl'],
//            'access_token'=>$authUser['access_token'],
//            'auth_userinfo'=> '1'
//        ];
//        if(!$third || !$third->user_id || !User::where('id',$third->user_id)->value('id')){
//            Cookie::set('token', '');
//            if(!$third){
//                $third_model->save($param);
//                $third = $third_model;
//            }
//
//           //创建授权信息的同时创建账号信息
//            $auth = (Auth::instance());
//            $ret = $auth->register($wechat_userinfo['nickname'], Random::alnum(), '', '', ['avatar'=>$wechat_userinfo['headimgurl'],'nickname'=>$wechat_userinfo['nickname']]);
//
//            Cookie::set('uid', $auth->id);
//            Cookie::set('token', $auth->getToken(),30 * 86400);
//            $third->user_id = $auth->id;
//            $third->save();
//        }else{
//            //if(!$token = Cookie::get('token')){
//                $user = User::get($third->user_id);
//                $auth = (Auth::instance());
//                $ret = $auth->direct($user->id);
//                Cookie::set('uid', $auth->id);
//                Cookie::set('token', $auth->getToken(),30 * 86400);
//            //}
//        }

        $target_url = !session('target_url') ? url('index/index/index') : session('target_url');
        $target = explode('?',$target_url);
        if(count($target) > 1){
            $domain = $target[0];
//            $query = $target[1].'&token='.Cookie::get('token');
            $query = $target[1].'&openid='.$wechat_userinfo['openid'];
            $target_url = $domain.'?'.$query;
        }else{
            $target_url .= '?openid='.$wechat_userinfo['openid'];
        }
        header('location:'.$target_url);
        //redirect($target_url);
    }

    //更新用户信息
    public function get_user_info($openid)
    {
        $userService = $this->app->user;
        try {
            return $userService->get($openid);
        } catch (Exception $e) {
            throw $e;
        }

    }


    /**
     * 生成统一订单
     */
    public function union_order($order){

        $orderinfo = [
            'body'              => $order['body'],
            'out_trade_no'      => $order['order_no'],
            'total_fee'         => (int)($order['pay_price'] * 100),
            //'spbill_create_ip'  => '123.12.12.123', // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'notify_url'        => $order['notify_url'], // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type'        => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid'            => $order['openid'],
        ];
        try {
            $wxpay = $this->payment->order->unify($orderinfo);
            if($wxpay['return_code'] == "FAIL" || $wxpay['result_code'] == "FAIL"){
                throw new Exception($wxpay['return_code'] == "FAIL"?$wxpay['return_msg']:$wxpay['err_code_des']);
            }
            return $this->payment->jssdk->bridgeConfig($wxpay['prepay_id'], false);
        }catch (Exception $e){
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 支付回调
     */
    public function notify()
    {
       // Log::record(file_get_contents('php://input'), "notify");
        $table = input('table','course_order');
        $response = $this->payment->handlePaidNotify(function ($message, $fail) use($table){
            // 你的逻辑
            Log::record($message, "debug");
            $order_no = $message['out_trade_no'];
            Db::startTrans();
            switch($table){
                case 'course_order':
                    try {
                        CourseOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'vip_order':
                    try {
                        VipOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'offline_order':
                    try {
                        OfflineOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'read_order':
                    try {
                        Readorder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
            }
            Db::commit();
            return true;

        });

        $response->send();
        return;
    }


    // 查询订单
    public function wxOrderQuery($out_trade_no)
    {
        $app = $this->app;
        $payment = $app->payment;
        $result = $payment->query($out_trade_no);
        return $result;
    }

    /**
     * 申请退款 只 支持1次性退款  退款表 id|apply_time|order_no|status|to_back_fee|reason|back_time
     * @param $order_no 订单号
     * @param $to_back_fee int 退款费 单位分
     * @param $reason string 退款理由
     */
    public function applyRefund($order_id, $to_back_fee,$refund_type='order', $reason = '')
    {

        $payment = $this->payment;

        switch($refund_type){
            case 'order':
                $order = db('order')->where('id',$order_id)->find();
                $orderInfo = $order;
                $wx_trade_no = $order['order_trade_no'];
                $wx_pay =$order['pay_price'];
                $refund_no = $order['order_trade_no'];
                break;
        }

        if (!$orderInfo) {
            //pubu("订单号 {$order_no}的订单记录不存在");
            return ['status'=>false,'msg'=>'退款订单不存在'];
        }
        if (!$order) {
            //pubu("订单号 {$order_no}的订单记录不存在");
            return ['status'=>false,'msg'=>'订单不存在'];
        }

        //测试情况 检测退款金额
//        if (config('app_debug')) {
//            $orderInfo['order_amount'] = 0.01;
//            $to_back_fee = 1;
//        }

        if ($to_back_fee > 100 * $order['pay_price']) {
            return ['status'=>false,'msg'=>'退款金额大于支付金额'];
        }
        try {
            $result = $payment->refund->byOutTradeNumber($wx_trade_no, $refund_no, $wx_pay * 100, $to_back_fee*100, [
                // 可在此处传入其他参数，详细参数见微信支付文档
                'refund_desc' => '商品退款',
            ]);
            if ('SUCCESS' != $result['return_code'] || "SUCCESS" != $result['result_code']) {
                $err_code_des = isset($result['err_code_des'])?'错误描述：'.$result['err_code_des']:'';
                $return_msg = strtolower($result['return_msg']) == 'ok'?$err_code_des:$result['return_msg'];

                return ['status' => false, 'msg' => "订单号：{$order['transaction_id']} 因{$reason} 申请的微信退款失败, 原因：{$return_msg}"];
            } else {
                return ['status'=>true,'msg'=>'退款成功'];
            }
        } catch (\Exception $e) {
            return ['status'=>false,'msg'=>"订单号：{$order['transaction_id']} 因{$reason} 申请的微信退款失败, 原因：{$e->getMessage()}"];
        }
    }


    /**
     * 申请提现订单  申请提现的记录表结果 id|uid|money|status|create_time|check_time|reason|order_no|reason
     * @param $withdraw array 提现记录数据
     */
    public function applyWithDraw($withdraw, $openid)
    {


        $app             = $this->app;
        $merchantPay     = $app->merchant_pay;
        $order_no        = $withdraw['applyno'];
        $merchantPayData = [
            'partner_trade_no' => $order_no, //随机字符串作为订单号，跟红包和支付一个概念。
            'openid'           => $openid, //收款人的openid
            'check_name'       => 'NO_CHECK', //文档中三分钟校验实名的方法NO_CHECK OPTION_CHECK FORCE_CHECK
            // 're_user_name'     => '张三', //OPTION_CHECK FORCE_CHECK 校验实名的时候必须提交
            'amount'           => $withdraw['money'] * 100, //单位为分 ，最少不能小于1元
            'desc'             => '用户提现',
            'spbill_create_ip' => get_client_ip(), //发起交易的IP地址
        ];
        //dump($merchantPayData);die;
        try {
            $result = $merchantPay->send($merchantPayData);
            //dump($result);die;
            if ('SUCCESS' == $result->return_code && 'SUCCESS' == $result->result_code) {

                return [
                    'code'   => 200,
                    'status' => true,
                    'info'   => '提现成功'
                ];
            } else {
                // M('Widthdraw')->where(['id'=>$withdraw['id']])->save(['status'=>0])
                return [
                    'code'   => 400,
                    'info'   => "{$result->err_code}：{$result->err_code_des}",
                    'status' => false,
                ];
            }
        } catch (\Exception $e) {
            return [
                'code'   => 400,
                'info'   => $e->getMessage(),
                'status' => false,
            ];
        }
    }


    /**
     * 发送模板消息
     * @author yangweijie
     * @param openid openid
     * @param $templateId
     * @param $data = array(
    "first"    => "恭喜你购买成功！",
    "keynote1" => "巧克力",
    "keynote2" => "39.8元",
    "keynote3" => "2014年9月16日",
    "remark"   => "欢迎再次购买！",
    );
     * @param $link
     * @param $color
     */
    public function send_template($openid, $templateId, $data, $link = '', $color = '')
    {
        try {
            $messageId = $this->app->template_message->send([
                'touser' => $openid,
                'template_id' => $templateId,
                'url' => $link,
                'data' => $data,
            ]);
            return ['status'=>true,'msg'=>$messageId];
        } catch (\Exception $e) {
            return ['status'=>false,'msg'=>"给{$openid} 发送templateId为{$templateId} 数据为" . var_export($data, true) . '的微信模板消息失败，失败原因:' . $e->getMessage()];
            return false;
        }
    }

}
